package com.xiaoq.shop.endpoint;

import com.alibaba.dubbo.config.annotation.Reference;
import com.xiaoq.apis.user.IUserApi;
import com.xiaoq.apis.user.UserInfo4UserCouponVo;
import com.xiaoq.coms.GenericDataResponse;
import com.xiaoq.coms.GenericListResponse;
import com.xiaoq.coms.GenericResponse;
import com.xiaoq.coms.util.IdGenerator;
import com.xiaoq.shop.entity.CouponEntity;
import com.xiaoq.shop.entity.SKUEntity;
import com.xiaoq.shop.entity.UserCouponEntity;
import com.xiaoq.shop.service.ISimpleLockService;
import com.xiaoq.shop.service.ICouponService;
import com.xiaoq.shop.service.ISKUService;
import com.xiaoq.shop.service.IUserCouponService;
import com.xiaoq.shop.vo.CouponVO;
import com.xiaoq.shop.vo.UserCouponDetailVo;
import com.xiaoq.shop.vo.UserCouponVo;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by chenjh on 2017/11/3.
 */
@RestController
@RequestMapping(value = "/api/v1/usercoupons")
public class UserCouponEndpoint2C {

    private static final Logger LOGGER = LoggerFactory.getLogger(UserCouponEndpoint2C.class);
    private static final class UserCouponDetailVoResponse extends GenericDataResponse<UserCouponDetailVo> {};
    private static final class UserCouponVoListResponse extends GenericListResponse<UserCouponVo> {};

    @Autowired
    private IUserCouponService userCouponService;

    @Autowired
    private ISKUService skuService;

    @Autowired
    private ICouponService couponService;

    @Autowired
    private ISimpleLockService simpleLockService;

    @Autowired
    private IdGenerator idGenerator;

    @Reference(interfaceClass=IUserApi.class, check=false, version="1.0.0")
    private IUserApi userDubboApi;

    @ApiOperation(value="用户的优惠券列表", notes="优惠券列表")
    @ApiResponses({
            @ApiResponse(code = 200, response = UserCouponDetailVoResponse.class, message = "优惠券列表")
    })
    @GetMapping(value="", produces={MediaType.APPLICATION_JSON_UTF8_VALUE})
    public ResponseEntity<?> userCouponList(HttpServletRequest request) {

        String userId = (String) request.getAttribute("userId");
        UserInfo4UserCouponVo userInfo4UserCouponVo = userDubboApi.getUserInfoById(userId);
        if(userInfo4UserCouponVo ==null || StringUtils.isBlank(userInfo4UserCouponVo.getId())){
            return GenericResponse.ng("此用户未登录或不存在");
        }

        UserCouponDetailVo userCouponDetailVo = userCouponService.getUserAllCouponListByUserId(userId);
        return UserCouponDetailVoResponse.okWithData(userCouponDetailVo);
    }

//    @ApiOperation(value="用户在某店的可用优惠券列表", notes="用户在某店的所有优惠券列表")
//    @ApiResponses({
//            @ApiResponse(code = 200, response = UserCouponDetailVoResponse.class, message = "用户在某店的所有优惠券列表")
//    })
//    @GetMapping(value="/shops/{shopId}", produces={MediaType.APPLICATION_JSON_UTF8_VALUE})
//    public ResponseEntity<?> userCouponListInShop(HttpServletRequest request,
//                                       @PathVariable("shopId") @ApiParam(value="店的Id", required=true) String shopId) {
//        //1、判断用户存在
//        String userId = (String) request.getAttribute("userId");
//        UserInfo4UserCouponVo userInfo4UserCouponVo = userDubboApi.getUserInfoById(userId);
//        if(userInfo4UserCouponVo ==null || StringUtils.isBlank(userInfo4UserCouponVo.getId())){
//            return GenericResponse.ng("此用户未登录或不存在");
//        }
//
//        UserCouponDetailVo userCouponDetailVo = userCouponService.getUserAllCouponList(shopId, userId);
//        return UserCouponDetailVoResponse.okWithData(userCouponDetailVo);
//    }

    @ApiOperation(value="下单时，查询用户在某店的可用优惠券列表", notes="下单时，查询用户在某店的可用优惠券列表")
    @ApiResponses({
            @ApiResponse(code = 200, response = UserCouponVoListResponse.class, message = "下单时，查询用户在某店的可用优惠券列表")
    })
    @GetMapping(value="/shops/{shopId}", produces={MediaType.APPLICATION_JSON_UTF8_VALUE})
    public ResponseEntity<?> userCanUseCouponListInShop(
            HttpServletRequest request,
            @PathVariable("shopId") @ApiParam(value="店的Id", required=true) String shopId,
            @RequestParam("number") @ApiParam(value="购买数量", required=true) int number,
            @RequestParam("spuCode") @ApiParam(value="spucode", required=true) String spuCode,
            @RequestParam("skuCode") @ApiParam(value="skucode", required=true) String skuCode) {

        //1、判断用户存在
        String userId = (String) request.getAttribute("userId");
        UserInfo4UserCouponVo userInfo4UserCouponVo = userDubboApi.getUserInfoById(userId);
        if(userInfo4UserCouponVo ==null || StringUtils.isBlank(userInfo4UserCouponVo.getId())){
            return GenericResponse.ng("此用户未登录或不存在");
        }

        SKUEntity skuEntity = skuService.getTicketSku(shopId, spuCode, skuCode);
        if(skuEntity == null || StringUtils.isBlank(skuEntity.getId())){
            return GenericResponse.ng("此SKU的商店不存在");
        }

        //该用户在该景区下的优惠券
        List<UserCouponVo> userCouponVoList = new ArrayList<>();
        UserCouponDetailVo userCouponDetailVo = userCouponService.getUserAllCouponList(shopId, userId);
        if(userCouponDetailVo == null || CollectionUtils.isEmpty(userCouponDetailVo.getUnusedCouponList())){
            return UserCouponVoListResponse.listAndCount(userCouponVoList, userCouponVoList.size());
        }

        //通过数量价格计算优惠券是否可用
        List<UserCouponVo> unUsedCouponList = userCouponDetailVo.getUnusedCouponList();
        unUsedCouponList.forEach(userCouponVo -> {
            if(number*skuEntity.getDiscountPrice()/100.0 >= userCouponVo.getMinSpendingAmountForUse()){
                userCouponVoList.add(userCouponVo);
            }
        });

        return UserCouponVoListResponse.listAndCount(userCouponVoList, userCouponVoList.size());
    }

    @ApiOperation(value="预约讲解员时，查询用户在某店的可用优惠券列表", notes="预约讲解员时，查询用户在某店的可用优惠券列表")
    @ApiResponses({
            @ApiResponse(code = 200, response = UserCouponVoListResponse.class, message = "预约讲解员时，查询用户在某店的可用优惠券列表")
    })
    @GetMapping(value="/sites/{sitesId}", produces={MediaType.APPLICATION_JSON_UTF8_VALUE})
    public ResponseEntity<?> userCanUseCouponListInShopForOrderInterpreter(
            HttpServletRequest request,
            @PathVariable("sitesId") @ApiParam(value="景区ID", required=true) String sitesId,
            @RequestParam("interpreterId") @ApiParam(value="interpreterId", required=true) String interpreterId) {

        String userId = (String) request.getAttribute("userId");
        UserInfo4UserCouponVo userInfo4UserCouponVo = userDubboApi.getUserInfoById(userId);
        if(userInfo4UserCouponVo == null || StringUtils.isBlank(userInfo4UserCouponVo.getId())){
            return GenericResponse.ng("此用户未登录或不存在");
        }

        SKUEntity skuEntity = skuService.getInterpreterSkuById(sitesId,interpreterId);
        if(skuEntity == null || StringUtils.isBlank(skuEntity.getId())){
            return GenericResponse.ng("讲解员不存在");
        }

        //该用户在该景区下的优惠券
        List<UserCouponVo> userCouponVoList = new ArrayList<>();
        UserCouponDetailVo userCouponDetailVo = userCouponService.getUserAllCouponList(sitesId, userId);
        if(userCouponDetailVo==null || CollectionUtils.isEmpty(userCouponDetailVo.getUnusedCouponList())){
            return UserCouponVoListResponse.listAndCount(userCouponVoList, userCouponVoList.size());
        }

        //通过数量价格计算优惠券是否可用
        List<UserCouponVo> unUsedCouponList = userCouponDetailVo.getUnusedCouponList();
        unUsedCouponList.forEach(userCouponVo -> {
            if(skuEntity.getDiscountPrice()/100.0 >= userCouponVo.getMinSpendingAmountForUse()){
                userCouponVoList.add(userCouponVo);
            }
        });

        return UserCouponVoListResponse.listAndCount(userCouponVoList, userCouponVoList.size());
    }

    @ApiOperation(value="用户领券", notes="用户领券")
    @ApiResponses({
            @ApiResponse(code = 200, response = GenericResponse.class, message = "用户领券")
    })
    @PostMapping(value = "", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity<?>  commitOrder(HttpServletRequest request, @RequestBody CouponVO couponVO) {

        String userId = (String) request.getAttribute("userId");
        UserInfo4UserCouponVo userInfo4UserCouponVo = userDubboApi.getUserInfoById(userId);
        if(userInfo4UserCouponVo == null || StringUtils.isBlank(userInfo4UserCouponVo.getId())){
            return GenericResponse.ng("用户未登录或不存在");
        }

        if(couponVO == null){
            return GenericResponse.ng("RequestBody 不能为空");
        }

        CouponEntity couponEntity = couponService.getCouponById(couponVO.getId());

        if(couponEntity==null || StringUtils.isBlank(couponEntity.getId()) || couponEntity.getExpirationDate()==null){
            return GenericResponse.ng("优惠券不存在");
        }

        if(couponEntity.getExpirationDate() < System.currentTimeMillis()){
            return GenericResponse.ng("此优惠券已过期");
        }

        if(couponEntity.getCount() == null){
            return GenericResponse.ng("该优惠券未设置数量");
        }

        String couponId = couponEntity.getId();

        int lockCount = 0;
        boolean lockOk = false;
        try {
            do {
                if (lockCount != 0) {
                    Thread.sleep(1000);
                }
                lockOk = simpleLockService.lock(couponId);
                lockCount++;

            } while (!lockOk && lockCount < 4);
        }catch (Exception e){
            LOGGER.error("锁优惠券失败", e.getMessage());
            //释放优惠券
             simpleLockService.releaseLock(couponId);
            return GenericResponse.ng("领取优惠券失败，请稍候再试");
        }

        if (!lockOk) {
            LOGGER.error("锁优惠券失败--{}", lockOk);
            return GenericResponse.ng("领取优惠券失败，请稍候再试");
        }

        UserCouponEntity userCouponEntity = new UserCouponEntity();
        BeanUtils.copyProperties(couponEntity, userCouponEntity);
        userCouponEntity.setUserId(userId);
        userCouponEntity.setId(idGenerator.nextId());
        userCouponEntity.setState(UserCouponEntity.StateEnum.NOUSE.value()); //未使用
        userCouponEntity.setNumberOfCoupons(1);
        userCouponEntity.setCouponInstanceCode(couponEntity.getId());
        userCouponEntity.setGetTime(System.currentTimeMillis());
        int limitCount = couponEntity.getLimitCount()==null?0:couponEntity.getLimitCount().intValue();
        int couponCount = couponEntity.getCount().intValue();
        int hasTakeCount = couponEntity.getTakenCount()==null?0:couponEntity.getTakenCount();
        if(couponCount == hasTakeCount){
            return GenericResponse.ng("优惠券已被领取完");
        }

        boolean successFlag = false;
        long userCouponNum = userCouponService.getUserCouponCount(userId, couponEntity.getId());

        if((userCouponNum>=limitCount) && (limitCount>0)){
            //释放优惠券
            simpleLockService.releaseLock(couponId);
            return GenericResponse.ng("您已领取优惠券");
        }

        if((userCouponNum < limitCount) || (limitCount == 0)){ //limitCount==0不限制领优惠券
            successFlag = userCouponService.saveUserCoupon(userCouponEntity);
        }

        if(successFlag){
            //TODO 更新领券数 + 1
            boolean isSuccess = couponService.incTakenCountPlus1(couponId);
            if(!isSuccess){
                LOGGER.error("用户["+userId+"]领取优惠券时，更新优惠券["+couponId+"]已被领取数量+1失败");
            }
        }else {
            return GenericResponse.ng("领取优惠券失败");
        }
        //释放优惠券
        simpleLockService.releaseLock(couponId);
        return GenericResponse.ok();
    }

    @ApiOperation(value="根据用户优惠券Id，删除过期的优惠券", notes="根据用户优惠券Id，删除过期的优惠券")
    @ApiResponses({
            @ApiResponse(code = 200, response = GenericResponse.class, message = "根据用户优惠券Id，删除过期的优惠券")
    })
    @DeleteMapping(value="", produces={MediaType.APPLICATION_JSON_UTF8_VALUE})
    public ResponseEntity<?> deleteUserCoupon(HttpServletRequest request,
                                              @RequestParam("userCouponIds") @ApiParam(value="用户的优惠券Id", required=true) String[] userCouponIds) {

        return getResponseEntity(request, userCouponIds);
    }

    @ApiOperation(value="根据用户优惠券Id，删除过期的优惠券(针对小程序)", notes="根据用户优惠券Id，删除过期的优惠券(针对小程序)")
    @ApiResponses({
            @ApiResponse(code = 200, response = GenericResponse.class, message = "根据用户优惠券Id，删除过期的优惠券(针对小程序)")
    })
    @GetMapping(value="/mini", produces={MediaType.APPLICATION_JSON_UTF8_VALUE})
    public ResponseEntity<?> deleteUserCoupon4MiniPro(HttpServletRequest request,
                                              @RequestParam("userCouponIds") @ApiParam(value="用户的优惠券Id", required=true) String[] userCouponIds) {

        return getResponseEntity(request, userCouponIds);
    }


    private ResponseEntity<?> getResponseEntity(HttpServletRequest request, @RequestParam("userCouponIds") @ApiParam(value = "用户的优惠券Id", required = true) String[] userCouponIds) {
        String userId = (String) request.getAttribute("userId");
        UserInfo4UserCouponVo userInfo4UserCouponVo = userDubboApi.getUserInfoById(userId);
        if(userInfo4UserCouponVo==null || StringUtils.isBlank(userInfo4UserCouponVo.getId())){
            return GenericResponse.ng("此用户未登录或不存在");
        }

        if(userCouponIds==null || userCouponIds.length==0){
            return GenericResponse.ng("请选择要删除的优惠券信息");
        }

        boolean delFlag = false;

        long currentTimeMillis = System.currentTimeMillis();
        for (String userCouponId : userCouponIds){
            UserCouponEntity userCouponEntity = userCouponService.getUserCouponById(userCouponId);
            if(userCouponEntity==null || !userId.equals(userCouponEntity.getUserId())){
                return GenericResponse.ng("优惠券不存在或此优惠券不属于此登录用户的");
            }

            long expiredDate = userCouponEntity.getExpirationDate()==null?0L:userCouponEntity.getExpirationDate();
            boolean isExpired = expiredDate < currentTimeMillis;

            if(isExpired || (userCouponEntity.getGetTime()!=null)){
                delFlag = userCouponService.deleteUserCoupon(userId,userCouponId);
            }
        }

        if(delFlag){
            return GenericResponse.ok();
        }

        return GenericResponse.ng("删除优惠券失败");
    }

}
